package lumis.portal.channel.template.serialization;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import lumis.portal.PortalException;
import lumis.portal.channel.template.ChannelTemplateLinkConfig;
import lumis.portal.manager.ManagerException;
import lumis.portal.manager.ManagerFactory;
import lumis.portal.manager.ManagerFactoryInternal;
import lumis.portal.serialization.BaseSerializationContext;
import lumis.portal.serialization.DeserializationContext;
import lumis.portal.serialization.SerializationContext;
import lumis.portal.serialization.operation.ConfigDependencyAnalyzer;
import lumis.portal.serialization.operation.ConfigForeignKey;

/**
 * Manager for Channel Template serialization
 *
 * @version $Revision: 12710 $ $Date: 2011-03-18 17:00:16 -0300 (Fri, 18 Mar 2011) $
 * @since 4.0.7
 */
public class ChannelTemplateSerializationManager implements IChannelTemplateSerializationManager
{
	private final String[] linkPrimaryKeyFieldNames = new String[] {"id"};
	protected final List<ConfigForeignKey> linkForeignKeys = Arrays.asList(new ConfigForeignKey[] {
			new ConfigForeignKey("templateChannelId", null, false, false, true, ManagerFactory.getChannelManager()),
			new ConfigForeignKey("destinationChannelId", null, false, false, true, ManagerFactory.getChannelManager()),
			new ConfigForeignKey("sourceId"),
			new ConfigForeignKey("destinationId")
		});

	private final String configAlias = "channelTemplateLink";
	
	// DESERIALIZATION
	
	private ChannelTemplateLinkConfig deserializeLinkConfig(DeserializationContext deserializationContext, String channelTemplateLinkId) throws ManagerException
	{
		deserializationContext.logDebug("Deserializing link config");
		return ManagerFactoryInternal.getSerializationManager2().deserializeObject(ChannelTemplateLinkConfig.class, deserializationContext.getDirectory(), getLinksConfigPath(deserializationContext, channelTemplateLinkId), configAlias, false);
	}

	public void deserializeLink(DeserializationContext deserializationContext, ChannelTemplateLinkSerializableConfig channelTemplateLinkSerializableConfig) throws PortalException
	{
		deserializationContext.logDebug("Deserializing link '" + channelTemplateLinkSerializableConfig.getId() + "'");

		// deserialize config
		ChannelTemplateLinkConfig channelTemplateLinkConfig = deserializeLinkConfig(deserializationContext, channelTemplateLinkSerializableConfig.getId());
		
		// apply primary key id mappings
		deserializationContext.applyPrimaryKeyFieldIdMappings(channelTemplateLinkConfig, linkPrimaryKeyFieldNames);
		
		// analyze dependencies and persist config
		ConfigDependencyAnalyzer dependencyAnalyzer = new ConfigDependencyAnalyzer<ChannelTemplateLinkConfig>(deserializationContext, linkForeignKeys, channelTemplateLinkConfig);
		dependencyAnalyzer.persist(this, false);
	}

	public boolean persistConfig(DeserializationContext deserializationContext, Object config, boolean firstPersistence) throws PortalException
	{
		ChannelTemplateLinkConfig channelTemplateLinkConfig = (ChannelTemplateLinkConfig)config;
		
		// apply foreign key id mappings
		deserializationContext.applyForeignKeyFieldIdMappings(channelTemplateLinkConfig, linkForeignKeys);

		// persists config
		deserializationContext.logDebug("Deserializing link:", channelTemplateLinkConfig);
		if (deserializationContext.isUpdateIfElementExists())
		{
			// delete original link, so the add operation will replace it
			ManagerFactory.getChannelTemplateManager().deleteChannelLink(deserializationContext.getSessionConfig(), channelTemplateLinkConfig.getId(), deserializationContext.getTransaction());
		}
		ManagerFactory.getChannelTemplateManager().addChannelLink(deserializationContext.getSessionConfig(), channelTemplateLinkConfig, deserializationContext.getTransaction());
		return true;
	}

	// SERIALIZATION
	
	public List<ChannelTemplateLinkSerializableConfig> serializeLink(SerializationContext serializationContext, String channelId) throws PortalException
	{
		List<ChannelTemplateLinkSerializableConfig> channelTemplateLinkSerializableConfigs = new ArrayList<ChannelTemplateLinkSerializableConfig>();
		
		for (ChannelTemplateLinkConfig channelTemplateLinkConfig : ManagerFactory.getChannelTemplateManager().getChannelLinks(serializationContext.getSessionConfig(), channelId, false, serializationContext.getTransaction()))
		{
			// serialize config
			ManagerFactoryInternal.getSerializationManager2().serializeObject(channelTemplateLinkConfig, serializationContext.getDirectory(), getLinksConfigPath(serializationContext, channelTemplateLinkConfig.getId()), configAlias);
	
			// build structure object
			channelTemplateLinkSerializableConfigs.add(createLinksSerializableConfig(channelTemplateLinkConfig));
		}
		
		return channelTemplateLinkSerializableConfigs;
	}

	private ChannelTemplateLinkSerializableConfig createLinksSerializableConfig(ChannelTemplateLinkConfig channelTemplateLinkConfig)
	{
		ChannelTemplateLinkSerializableConfig channelTemplateLinkSerializableConfig = new ChannelTemplateLinkSerializableConfig();
		channelTemplateLinkSerializableConfig.setId(channelTemplateLinkConfig.getId());
		return channelTemplateLinkSerializableConfig;
	}

	// GENERAL
	
	public void setupSerializationContext(BaseSerializationContext baseSerializationContext)
	{
		// define serialization aliases
		baseSerializationContext.getSerializationSettings().getClassAliases().put(ChannelTemplateLinkSerializableConfig.class, "channelTemplateLink");
	}

	private String getLinksConfigPath(BaseSerializationContext baseSerializationContext, String configId)
	{
		return "channelTemplateLinks/" + configId + ".xml";
	}
	
}
